package com.baidu.mpks.tree.service;

import com.baidu.mpks.tree.dao.UserTreeNodeDao;
import com.baidu.mpks.tree.domain.UserTreeNode;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;

@Service
public class UserTreeServiceImpl implements UserTreeService {
    private static final Logger log = LoggerFactory.getLogger(UserTreeServiceImpl.class);
    @Autowired
    private UserTreeNodeDao userTreeNodeDao;

    public UserTreeServiceImpl() {
    }

    private Map<Integer, Set<Integer>> geneAncestorMap(List<UserTreeNode> tree) {
        if (CollectionUtils.isEmpty(tree)) {
            return new HashMap();
        } else {
            Map<Integer, Set<Integer>> id2Parents = new HashMap();
            Iterator var3 = tree.iterator();

            while(var3.hasNext()) {
                UserTreeNode userTreeNode = (UserTreeNode)var3.next();
                Set<Integer> parents = (Set)id2Parents.get(userTreeNode.getId());
                if (parents == null) {
                    parents = new HashSet();
                    id2Parents.put(userTreeNode.getId(), parents);
                }

                if (userTreeNode.getParentId() != 0 && userTreeNode.getParentId() >= 0) {
                    ((Set)parents).add(userTreeNode.getParentId());
                }
            }

            var3 = id2Parents.keySet().iterator();

            while(true) {
                HashSet curparents;
                Integer id;
                Set parents;
                do {
                    do {
                        if (!var3.hasNext()) {
                            return id2Parents;
                        }

                        id = (Integer)var3.next();
                        parents = (Set)id2Parents.get(id);
                        curparents = new HashSet();
                    } while(parents == null);
                } while(parents.isEmpty());

                while(curparents.size() != parents.size()) {
                    curparents.addAll(parents);
                    parents.clear();
                    Iterator var7 = curparents.iterator();

                    while(var7.hasNext()) {
                        Integer curId = (Integer)var7.next();
                        parents.add(curId);
                        Set<Integer> temp = (Set)id2Parents.get(curId);
                        if (temp != null) {
                            parents.addAll(temp);
                        }
                    }
                }

                id2Parents.put(id, parents);
            }
        }
    }

    public Set<String> getParentsById(Integer nodeId) {
        List<UserTreeNode> allNodes = this.userTreeNodeDao.getTreeNodes();
        Map<Integer, Set<Integer>> parentNodesMap = this.geneAncestorMap(allNodes);
        Set<String> parentNodes = (Set)((Set)parentNodesMap.get(nodeId)).stream().map((item) -> {
            return item.toString();
        }).collect(Collectors.toSet());
        return parentNodes;
    }

    private Set<Integer> geneChildrenMap(List<UserTreeNode> tree, Integer pid, Set<Integer> childMenu) {
        Iterator var4 = tree.iterator();

        while(var4.hasNext()) {
            UserTreeNode userTreeNode = (UserTreeNode)var4.next();
            if (!userTreeNode.getParentId().equals(0) && userTreeNode.getParentId().equals(pid)) {
                this.geneChildrenMap(tree, userTreeNode.getId(), childMenu);
                childMenu.add(userTreeNode.getId());
            }
        }

        return childMenu;
    }

    public Set<Integer> getChildrensNotIncludeSelf(Integer nodeId) {
        List<UserTreeNode> allNodes = this.userTreeNodeDao.getTreeNodes();
        Set<Integer> childMenu = new CopyOnWriteArraySet();
        Set<Integer> id2Childrens = this.geneChildrenMapNotIncludeSelf(allNodes, nodeId, childMenu);
        return id2Childrens;
    }

    private Set<Integer> geneChildrenMapNotIncludeSelf(List<UserTreeNode> tree, Integer pid, Set<Integer> childMenu) {
        Iterator var4 = tree.iterator();

        while(var4.hasNext()) {
            UserTreeNode userTreeNode = (UserTreeNode)var4.next();
            if (userTreeNode.getParentId() != 0 && userTreeNode.getParentId() == pid) {
                this.geneChildrenMap(tree, userTreeNode.getId(), childMenu);
                childMenu.add(userTreeNode.getId());
            }
        }

        return childMenu;
    }

    public Set<Integer> getChildrensIncludeSelf(Integer nodeId) {
        List<UserTreeNode> allNodes = this.userTreeNodeDao.getTreeNodes();
        Set<Integer> childMenu = new CopyOnWriteArraySet();
        Set<Integer> id2Childrens = this.geneChildrenMap(allNodes, nodeId, childMenu);
        id2Childrens.add(nodeId);
        return id2Childrens;
    }

    public List<UserTreeNode> getTreeNodes() {
        return this.userTreeNodeDao.getTreeNodes();
    }
}
